package com.wang.nowcoder.service;

import com.wang.nowcoder.pojo.User;
import com.wang.nowcoder.util.CommunityConstant;
import com.wang.nowcoder.util.RedisKeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author wang
 * @ClassName FollowService
 * @Description 关注，取关
 * @date 2021/12/28 10:47
 * @Version 1.0
 */
@Service
@SuppressWarnings("all")
public class FollowService implements CommunityConstant {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserService userService;

    /**
     * 添加关注
     *
     * @param userId   用户Id
     * @param pojoType 实体类型
     * @param pojoId   实体ID
     */
    public void follow(int userId, int pojoType, int pojoId) {
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                String followKey = RedisKeyUtil.getFollowKey(userId, pojoType);
                String followerKey = RedisKeyUtil.getFollowerKey(pojoType, pojoId);
                operations.multi();
                operations.opsForZSet().add(followKey, pojoId, System.currentTimeMillis());
                operations.opsForZSet().add(followerKey, userId, System.currentTimeMillis());
                return operations.exec();
            }
        });
    }

    /**
     * 取消关注
     *
     * @param userId   用户Id
     * @param pojoType 实体类型
     * @param pojoId   实体ID
     */
    public void unFollow(int userId, int pojoType, int pojoId) {
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                String followKey = RedisKeyUtil.getFollowKey(userId, pojoType);
                String followerKey = RedisKeyUtil.getFollowerKey(pojoType, pojoId);
                operations.multi();
                operations.opsForZSet().remove(followKey, pojoId);
                operations.opsForZSet().remove(followerKey, userId);
                return operations.exec();
            }
        });
    }

    /**
     * 查询关注的实体的数量
     *
     * @param userId
     * @param pojoType
     * @return
     */
    public long selectFollowCount(int userId, int pojoType) {
        String followKey = RedisKeyUtil.getFollowKey(userId, pojoType);
        return redisTemplate.opsForZSet().zCard(followKey);
    }

    /**
     * 查询实体的粉丝数量
     *
     * @param pojoType
     * @param pojoId
     * @return
     */
    public long selectFollowerCount(int pojoType, int pojoId) {
        String followerKey = RedisKeyUtil.getFollowerKey(pojoType, pojoId);
        return redisTemplate.opsForZSet().zCard(followerKey);
    }

    /**
     * 查询当前用户是否已关注该实体
     *
     * @param userId
     * @param pojoType
     * @param pojoId
     * @return
     */
    public boolean hasFollowed(int userId, int pojoType, int pojoId) {
        String followeeKey = RedisKeyUtil.getFollowKey(userId, pojoType);
        return redisTemplate.opsForZSet().score(followeeKey, pojoId) != null;
    }

    /**
     * 查询某用户关注的人
     * @param userId
     * @param offset
     * @param limit
     * @return
     */
    public List<Map<String, Object>> findFollows(int userId,int offset,int limit){
        String followKey = RedisKeyUtil.getFollowKey(userId,ENTITY_TYPE_USER);
        Set<Integer> targetIds = redisTemplate.opsForZSet().reverseRange(followKey, offset, offset + limit - 1);
        if (targetIds == null){
            return null;
        }
        List<Map<String, Object>> list = new ArrayList<>();
        for (Integer targetId : targetIds) {
            Map<String, Object> map = new HashMap<>();
            User user = userService.selectById(targetId);
            map.put("user",user);
            Double score = redisTemplate.opsForZSet().score(followKey, targetId);
            map.put("followTime",new Date(score.longValue()));
            list.add(map);
        }
        return list;
    }

    public List<Map<String, Object>> findFollowers(int userId,int offset,int limit) {
        String followerKey = RedisKeyUtil.getFollowerKey(ENTITY_TYPE_USER,userId);
        Set<Integer> targetIds = redisTemplate.opsForZSet().reverseRange(followerKey, offset, offset + limit - 1);
        if (targetIds == null){
            return null;
        }
        List<Map<String, Object>> list = new ArrayList<>();
        for (Integer targetId : targetIds) {
            Map<String, Object> map = new HashMap<>();
            User user = userService.selectById(targetId);
            map.put("user",user);
            Double score = redisTemplate.opsForZSet().score(followerKey, targetId);
            map.put("followTime",new Date(score.longValue()));
            list.add(map);
        }
        return list;
    }
}
